package org.oep.jmingle;

import java.util.Random;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * This is the main midlet. You'll notice that we implement EventPipe in this class
 * so that our screens can have the Midlet change the screen for localized events.
 * @author pmkilgo
 *
 */
public class JMingle extends MIDlet implements EventPipe {
	public static final String VERSION = "v1.1";
	public static final Font DEFAULT_FONT = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
	public static final Font BOLD_FONT = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL );
	public static final Random RANDOM = new Random();
	
	// Our handlers
	private MingleTracker mingleHandler;
	
	// The screens
	private LandingScreen title;
	private Field activeScreen;
	
	// Misc. crap
	private Display display;
	
	private boolean initialized = false;
	
	
	public static final int SHOW_TUTORIAL = 0;
	public static final int SHOW_FIELD = 1;
	public static final int SHOW_MAIN = 2;
	public static final int QUIT_APP = 3;
	
	public JMingle() {

	}
	
	/*
	 * Inherited from MIDlet
	 */
	//--------------------------------------------------------------//

	/**
	 * When the app is shutting down, let's do a simple check to make sure the
	 * mingle database in memory matches  the one in storage. If the counts are
	 * unequal, we try to synchronize the storage with what we have in memory.
	 */
	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		if(mingleHandler.getRecordSize() != mingleHandler.getCacheSize()) {
			mingleHandler.exportToRecordStore();
		}
				
	}

	/**
	 * This will stop all threads while the app is sleeping.
	 */
	protected void pauseApp() {
		if(activeScreen != null) {
			activeScreen.pause();
		}
	}

	/**
	 * This function is pretty delicate. It sets up pretty much all the screens
	 * necessary for the basic execution of JMingle. Order is pretty important
	 * in the initialization. Here's the basic rundown:
	 * 
	 * 1. Create the screens
	 * 2. Set up event handling. Pass a reference to this class.
	 * 3. Set up the mingle tracker which should be global for the entire app.
	 * 4. Show the loading screen and load the mingles.
	 * 5. Show the splash.
	 * 6. Change the boolean variable 'initialized' so we don't accidentally
	 * 		reinitialize everything.
	 */
	protected void startApp() throws MIDletStateChangeException {
		// Please note that the order in which we initialize some things is very
		// important. Things that are constructed using 'this' are in here, and
		// some are interdependent on one another.
		
		if(!initialized) {
			display = Display.getDisplay(this);
			
			// We three screens...
			title = new LandingScreen(this);

			// Load the mingler.
			mingleHandler = new MingleTracker(this);
			
			// Try to show a fluffy loading screen
			LoadScreen loadScreen = new LoadScreen(mingleHandler);
			SplashScreen theSplash = new SplashScreen();
			theSplash.setEventHandler(this);
			display.setCurrent(loadScreen);
			
			// Start the load
			mingleHandler.doLoad();
			loadScreen.die();
			loadScreen = null;
			
			theSplash.goBuddy();
			display.setCurrent(theSplash);
			
			initialized = true;
		}
		
		resumeProperScreen();
	}
	
	/*
	 * Inherited from EventPipe
	 */
	//--------------------------------------------------------------//
	
	/**
	 * This is our main signal processor. Mainly this is just a quick 'n dirty
	 * way to have other classes be able to control which screen is being
	 * displayed. 
	 */
	public void eventReceived(int event) {
		switch(event) {
		case SHOW_TUTORIAL: showTutorial(); break;
		case SHOW_FIELD: showField(); break;
		case SHOW_MAIN: showTitle(); break;
		case QUIT_APP: quitApp(); break;
		}
	}
	

	/*
	 * For internal use
	 */
	//--------------------------------------------------------------//
	
	/**
	 * This is an internal alias to switch the current screen to the tutorial.
	 */
	private void showTutorial() {
		activeScreen = Field.constructField(mingleHandler, this);
		activeScreen.toInitialState();
		activeScreen.setTutorial(true);
		activeScreen.start();
		display.setCurrent(activeScreen);
	}
	
	/**
	 * This is an internal alias to show The Field.
	 */
	private void showField() {
		activeScreen = Field.constructField(mingleHandler, this);
		activeScreen.toInitialState();
		activeScreen.setTutorial(false);
		activeScreen.start();
		display.setCurrent(activeScreen);
	}
	
	/**
	 * This is an internal alias to show the title screen.
	 */
	private void showTitle() {
		if(activeScreen != null) {
			activeScreen.pause();
			activeScreen = null;
		}
		title.toInitialState();
		display.setCurrent(title);
	}
	
	/**
	 * Ideally the Midlet ought to pause threads in other screens that
	 * aren't necessary. This function just checks the current screen and
	 * resumes that thread if it is necessary.
	 */
	private void resumeProperScreen() {
		if(display.getCurrent() == activeScreen && activeScreen != null) {
			activeScreen.start();
		}
	}
	
	/**
	 * This is just an alias to properly end the Midlet.
	 */
	private void quitApp() {
		try {
			destroyApp(false);
		}
		catch(Exception e) { 
			
		}
        notifyDestroyed();	
	}
	
	public static final String
		TUTORIAL_SCRIPT = "/res/text/tut-script.txt";
}
